# 使用yield+next实现多任务，太麻烦必须手动调用，此时可以使用greenlet替换yield
from greenlet import greenlet
import time
import gevent
from gevent import monkey


def test1():
    while True:
        print("test1")
        # test1执行结束后切换到test2继续执行
        gr2.switch()
        time.sleep(0.5)


def test2():
    while True:
        print("test2")
        gr1.switch()
        time.sleep(0.5)


gr1 = greenlet(test1)
gr2 = greenlet(test2)

"""
使用gevent：网络并发库 内部使用协程实现
greenlet是yield的封装，gevent是对greenlet的再封装
"""


def fn(n):
    """协程依赖于线程，在一个方法中如果有耗时操作，在等待耗时的过程中执行其他函数"""

    # 一个项目中如果使用了大量time.sleep等此时需要协程，需要换成gevent模块下的相关方法，重构起来耗时耗力
    # gevent提供了打补丁的操作,此时即使使用time模块也可以实现协程
    monkey.patch_all()

    for i in range(n):
        print(gevent.getcurrent(), i)
        # 协程要切换任务必须是一个任务中有耗时操作，此时不能使用time模块下的sleep而是使用gevent中的
        time.sleep(0.5)
        # gevent.sleep(0.5)


def test_gevent():
    # 相当于孵化一个协程
    g1 = gevent.spawn(fn, 5)
    g2 = gevent.spawn(fn, 5)
    g3 = gevent.spawn(fn, 5)

    g1.join()
    g2.join()
    g3.join()

    # 上述每启动一个协程都要调用join方法有点繁琐，gevent提供joinall方法同时启动
    # gevent.joinall([
    #     gevent.spawn(fn, 5),
    #     gevent.spawn(fn, 5),
    #     gevent.spawn(fn, 5)
    # ])


def main():
    test_gevent()


if __name__ == '__main__':
    main()
